package com.stadium.common.utils;

import com.stadium.common.exception.RRException;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {

    /** 日期格式 */
    public static final String FORMAT_DATE = "yyyy-MM-dd";
    public static final Integer[] LASTDAY = new Integer[]{31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    /**
     * 当前周的周一和周日
     *
     * @param date 日期
     * @return
     */
    public static Date[] days_week(Date date) {
        //DAY_OF_WEEK-1 对应周几
        Date[] weeks = new Date[2];
        int[] week = {7, 1, 2, 3, 4, 5, 6};
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        //date是否为周一
        if (week[day - 1] != 1) {
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - week[day - 1] + 1);
        }
        weeks[0] = calendar.getTime();
        weeks[1] = new Date(calendar.getTime().getTime() + (long) 6 * 24 * 60 * 60 * 1000);
        return weeks;
    }

    /***
     * 当前月的第一天和最后一天
     * @param date
     * @return
     */
    public static Date[] days_month(Date date) {
        Date[] months = new Date[2];
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        //本月第一天
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        months[0] = calendar.getTime();
        //下月第一天
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - 1);
        months[1] = calendar.getTime();
        return months;
    }

    public static Integer getLastDay(String month, String year) {
        return getLastDay(Integer.parseInt(month), Integer.parseInt(year));
    }

    public static Integer getLastDay(Integer m, Integer year) {
        --m;
        if(m != 1){
            return LASTDAY[m];
        }else{
            year = (year == null ? Calendar.getInstance().get(Calendar.YEAR) : year);
            return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? 29 : 28;
        }
    }

    /***
     * 月份周
     * @param month 月份
     * @return
     */
    public static String[] weeks(String month) {
        StringBuffer stringBuffer = new StringBuffer("");
        //DAY_OF_WEEK-1 对应周几
        int[] week = {7, 1, 2, 3, 4, 5, 6};
        Calendar calendar = Calendar.getInstance();
        Calendar _calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.toDate(month, "yyyy-MM"));
        _calendar.setTime(DateUtil.toDate(month, "yyyy-MM"));
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        int weeks = 4;
        if (week[day - 1] != 1) {
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - week[day - 1] + 1);
            weeks++;
        }
        for (int i = 1; i <= weeks; i++) {
            stringBuffer.append(DateUtil.toDate(calendar.getTime(), "yyyy-MM-dd") + ",");
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 6);
            stringBuffer.append(DateUtil.toDate(calendar.getTime(), "yyyy-MM-dd") + ",");
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 1);
        }
        if (calendar.get(Calendar.MONTH) == _calendar.get(Calendar.MONTH)) {
            stringBuffer.append(DateUtil.toDate(calendar.getTime(), "yyyy-MM-dd") + ",");
            calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) + 6);
            stringBuffer.append(DateUtil.toDate(calendar.getTime(), "yyyy-MM-dd") + ",");
        }
        stringBuffer.setLength(stringBuffer.length() - 1);
        return stringBuffer.toString().split(",");
    }

    /***
     * 日期月份对比
     * @param beginDate 开始日期
     * @param endDate 结束日期
     * @return
     */
    public static int months(Date beginDate, Date endDate) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(beginDate);
        c2.setTime(endDate);
        if (c2.getTimeInMillis() < c1.getTimeInMillis()) {
            return 0;
        }
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        // 获取年的差值 假设 d1 = 2015-9-30 d2 = 2015-12-16
        int yearInterval = year2 - year1;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if (month2 < month1 || month1 == month2 && day2 < day1) {
            yearInterval--;
        }
        // 获取月数差值
        int monthInterval = (month2 + 12) - month1;
        if (day2 > day1) {
            monthInterval++;
        }
        monthInterval %= 12;
        return yearInterval * 12 + monthInterval;
    }

    /**
     * 天数差
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    public static Integer days(Date beginDate, Date endDate) {
        int days = (int) ((endDate.getTime() - beginDate.getTime()) / (1000 * 3600 * 24));
        return days;
    }

    public static String strDays_(Date beginDate, Date endDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - beginDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        if (day != 0) {
            return day + "天" + (hour != 0 ? hour + "小时" : "");
        }
        if (min == 0) {
            min = 1;
        }
        return (hour == 0 ? "" : hour + "小时") + min + "分钟";
    }

    public static String strDays(Date beginDate, Date endDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - beginDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        if (day != 0) {
            return day + "天";
        }
        if (hour != 0) {
            return hour + "小时";
        }
        if (min != 0) {
            return min + "分钟";
        }
        return "1分钟";
    }

    /***
     * 当月第一天和最后一天
     * @param format
     * @return
     */
    public static String[] monthDate(String format) {
        String[] date = {"", ""};
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        //获取当前月第一天：
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        date[0] = dateFormat.format(c.getTime());
        //获取当前月最后一天
        Calendar ca = Calendar.getInstance();
        //ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        date[1] = dateFormat.format(ca.getTime());
        return date;
    }

    public static String[] dayDate(String format, int day) {
        String[] date = {"", ""};
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        Calendar c = Calendar.getInstance();
        if (c.get(Calendar.DATE) < day) {
            c.set(Calendar.MONTH, c.get(Calendar.MONTH) - 1);
        }
        c.set(Calendar.DAY_OF_MONTH, 1);
        date[0] = dateFormat.format(c.getTime());
        date[1] = dateFormat.format(new Date());
        return date;
    }

    public static String[] weekDate(String format) {
        String[] date = {"", ""};
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        //获取当前月第一天：
        Calendar c = Calendar.getInstance();
        date[1] = dateFormat.format(c.getTime());
        c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) - 7);
        date[0] = dateFormat.format(c.getTime());
        return date;
    }

    public static String toTime(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("HH:mm:ss");
        return fdateFormater.format(date);
    }

    public static String toDate(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("M月d日");
        return fdateFormater.format(date) + "（" + getWeekOfDate(date) + "）";
    }

    public static String toDate(String date, String originalformat, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(originalformat);
        SimpleDateFormat fdateFormater = new SimpleDateFormat(format);
        Date _date = null;
        try {
            _date = sdf.parse(date);
            return fdateFormater.format(_date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    public static String toDate(Date date, String format) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat(format);
        return fdateFormater.format(date);
    }

    public static String now(String format) {
        Date now = new Date();
        SimpleDateFormat fdateFormater = new SimpleDateFormat(format);
        return fdateFormater.format(now);
    }

    public static String toLastWeek(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("M月d日");
        Date _date = new Date(date.getTime() - (long) 6 * 24 * 60 * 60 * 1000);
        return fdateFormater.format(_date) + "-" + fdateFormater.format(date);
    }

    public static Date addDate(Date date, int days) {
        return new Date(date.getTime() + (long) days * 24 * 60 * 60 * 1000);
    }


    public static Date lastWeek(Date date) {
        return new Date(date.getTime() - (long) 6 * 24 * 60 * 60 * 1000);
    }

    public static Date lastYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) - 1);
        return calendar.getTime();
    }

    public static Date lastMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        return calendar.getTime();
    }

    public static Date yesterday(Date date) {
        return new Date(date.getTime() - (long) 1 * 24 * 60 * 60 * 1000);
    }


    public static String toNextWeek(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("M月d日");
        Date _date = new Date(date.getTime() + (long) 6 * 24 * 60 * 60 * 1000);
        return fdateFormater.format(date) + "-" + fdateFormater.format(_date);
    }

    public static Date NextWeek(Date date) {
        return new Date(date.getTime() + (long) 6 * 24 * 60 * 60 * 1000);
    }

    public static Date nextYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, 1);
        return calendar.getTime();
    }

    public static Date nextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        return calendar.getTime();
    }

    public static String toNextMonth(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("M月d日");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        return fdateFormater.format(date) + "-" + fdateFormater.format(calendar.getTime());
    }

    public static String toLastMonth(Date date) {
        SimpleDateFormat fdateFormater = new SimpleDateFormat("M月d日");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        return fdateFormater.format(calendar.getTime()) + "-" + fdateFormater.format(date);
    }

    public static Date NextMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        return calendar.getTime();
    }

    public static Date toDate(Date date, int field, int value) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(field, calendar.get(field) + value);
        return calendar.getTime();
    }

    public static boolean firstDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DATE) == 1 ? true : false;
    }

    /**
     * 当天起止时间
     *
     * @return
     */
    public static Date[] timeDay() {
        Date[] time = new Date[2];
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 000);
        time[0] = calendar.getTime();
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        time[1] = calendar.getTime();
        return time;
    }

    public static Date toDate(String date, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date _date = null;
        try {
            _date = sdf.parse(date);
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return _date;
    }

    private static String getWeekOfDate(Date date) {
        String[] weekDays = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0) {
            w = 0;
        }
        return weekDays[w];
    }

    public static Date getTimesmorning() {
        Calendar cal = Calendar.getInstance();
        cal.set(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        Date beginOfDate = cal.getTime();
        return beginOfDate;
    }


    public static String hikTime(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateStr = sdf.format(date);
        sdf = new SimpleDateFormat("HH:mm:ss");
        String timeStr = sdf.format(date);
        StringBuilder sb = new StringBuilder();
        sb.append(dateStr).append("T").append(timeStr).append("+08:00");
        return sb.toString();
    }

    // 2019-07-17T08:00:22+08:00
    public static String hikTime(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        String t = dateStr.replace("T", " ").replace("+08:00", "");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            sdf.parse(t);
            return t;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date hikTime(String dateStr, String formate) {
        if (StringUtils.isEmpty(dateStr)) {
            return null;
        }
        String t = dateStr.replace("T", " ").replace("+08:00", "");
        SimpleDateFormat sdf = new SimpleDateFormat(formate);
        try {
            Date parse = sdf.parse(t);
            return parse;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String formatDate(Integer year, Integer month, Integer day) {
        String monthStr = month < 10 ? "0" + month : month.toString();
        String dayStr = day < 10 ? "0" + day : day.toString();
        return String.format("%d-%s-%s", year, monthStr, dayStr);
    }

    /**
     * 获取上一天
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static String formatLastDate(Integer year, Integer month, Integer day) {
        String monthStr = month < 10 ? "0" + month : month.toString();
        String dayStr = day < 10 ? "0" + day : day.toString();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = format.parse(String.format("%d-%s-%s", year, monthStr, dayStr));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return format.format(calendar.getTime());
    }

    /**
     * 获取当前月的所有日期
     *
     * @param date yyyy-MM
     * @return
     */
    public static List<String> getDateInMonth(String date) {
        String[] arr = date.split("-");
        Integer year = Integer.parseInt(arr[0]);
        Integer month = Integer.parseInt(arr[1]);
        return getDateInMonth(year, month);
    }

    public static List<String> getDateInMonth(Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month);
        calendar.set(Calendar.DAY_OF_MONTH, -1);
        int lastday = calendar.get(Calendar.DAY_OF_MONTH);
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= lastday + 1; i++) {
            list.add(i < 10 ? "0" + i : "" + i);
        }
        return list;
    }

    /**
     *  生效状态 0未生效 1已生效 2已过期 3延时失效
     */
    public static final Integer BEFORE_AUTH = 0;
    public static final Integer IN_AUTH = 1;
    public static final Integer OVER_AUTH = 2;
    public static final Integer DELAY_AUTH = 3;
    /**
     * 计算授权状态
     * @param start 授权开始日
     * @param end 授权开始日
     * @param tar 当前时间
     * @param delayDay 缓冲期
     * @return
     */
    public static int getAuthStatus(String start, String end, Long tar, Integer delayDay) {

        String tarDate = DateFormatUtils.format(tar, FORMAT_DATE);
        if(Objects.compare(end , tarDate, Comparator.naturalOrder()) < 0){
            if (delayDay != null && delayDay > 0) {
                Date delayEnd;
                try {
                    delayEnd = DateUtils.addDays(DateUtils.parseDate(end, FORMAT_DATE), delayDay);
                    if(Objects.compare(DateFormatUtils.format(delayEnd, FORMAT_DATE), tarDate, Comparator.naturalOrder()) >= 0){
                        return DELAY_AUTH;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            return OVER_AUTH;
        }else if(Objects.compare(start , tarDate, Comparator.naturalOrder()) > 0){
            return BEFORE_AUTH;
        }else{
            return IN_AUTH;
        }
    }

    public static Integer dateCompare(Date date, String startDate, String endDate) {
        Integer status = null; // null:异常  -1:未开始  0:在开始和结束之间  1:在结束日期之外
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Date currentDate = date;
        long start = 0;
        try {
            start = df.parse(startDate).getTime();

            long end = df.parse(endDate).getTime();
            String strCurrent = df.format(date);
            long current = df.parse(strCurrent).getTime();

            if (current < start) {
                status = -1;
            }

            if (current >= start && current <= end) {
                status = 0;
            }

            if (current > end) {
                status = 1;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (status == null) {
            throw new RRException("时间参数错误");
        }
        return status;
    }

    /**
     * 毫秒转日期（格式：1999-12-31 23:59:59）
     * @param millSec
     * @return
     */
    public static String transferLongToDate(Long millSec){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date= new Date(millSec);
        return sdf.format(date);
    }

    public static java.sql.Date toSqlDate(String date, String format) {
        if(StringUtils.isEmpty(date)) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Date _date = null;
        try {
            _date = sdf.parse(date);
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return new java.sql.Date(_date.getTime());
    }

    /**
     * 计算两个日期之间的总天数 yyyy-MM-dd格式
     * @return
     */
    public static int daysBetween2Date(String beginDate, String endDate){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return (int)((sdf.parse(endDate).getTime() - sdf.parse(beginDate).getTime())/(1000*60*60*24)) +1;
        } catch (ParseException e) {
            throw new RRException("日期计算错误");
        }
    }

    /**
     * 当前月剩余天数
     * @author CaoWei
     * @createDate 10:14 2021-03-29
     * @param now 当前日期 yyyy-MM-dd
     * @version 1.0.0
     */
    public static int remainingDays2MonthEnd(String now){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(now);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            int max = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
            int days = calendar.get(Calendar.DAY_OF_MONTH);
            return max - days + 1;
        } catch (ParseException e) {
            throw new RRException("日期计算错误");
        }
    }

    /**
     * 获取日期所在月的总天数 yyyy-MM-dd
     * @return
     */
    public static int maxDays(String now){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = sdf.parse(now);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
        } catch (ParseException e) {
            throw new RRException("日期计算错误");
        }
    }

}
